<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<link rel="stylesheet" href="../examples/css/style.css" type="text/css" media="screen"/>

	<!--[if lt IE 7]>
		<link rel="stylesheet" href="../examples/css/ie_lt_7.css" type="text/css"/>
	<![endif]-->

</head>
<body>
	<div id="wrapper" class="container_12 clear">
	
	<div class="grid_6">
		
	<h1>How to use jFrame</h1>

	<p>As our use of javascript increases we need new ways to organise and maintain our increasing large javascript code bases.  Normally when we use javascript we add script tags into a web page. Depending on how much javascript is needed you can have a large numbers of script tags in your web page. The order of the javascript files may also be important if your scripts have a number of dependancies. This approach can have a number of disadvantages:</p>

	<ul>
		<li>Maintainability: As the amount of javascript code increases it becomes harder to maintain especially if you have no clear folder structure.</li>
		<li>Coupling: The HTML and javascript is tightly coupled. If you change a javascript file you have to change each HTML page that file was used in.</li>
		<li>Unnecessary large file sizes - often we merge javascript files together to increase performance, for large websites this can often lead to a user only using a small subset of the loaded javascript functionality.</li>
	</ul>

	<p>This article details a framework called <a href="http://code.google.com/p/jsjframe/" title="View the jFrame website">jFrame</a> written by myself and a colleague <a href="http://benhaldenby.co.uk/" title="Ben Halendby's website">Ben Haldenby</a>. jFrame as been written on top of <a href="http://jquery.com/" title="jQuery homepage">jQuery</a> to overcome these disadvantages with the following features:</p>

	<ul>
		<li>components are organised into a clear folder structure</li>
		<li>decouples javascript from the HTML</li>
		<li>scripts are treated as discreet components with an elegant lazy loading and activation system</li>
		<li>the ability to use namespaces</li>
		<li>rather than loading one monolithic script, we only load the scripts necessary for the current page/user path</li>
		<li>the ability to cache and preload javascript files</li>
		<li>verbose debugging (which fails gracefully in IE)</li>
	</ul>

	<p>We will now go through and show how jFrame works with a number of examples.</p>

	<h2>Organising components into a clear folder structure</h2>
	<p>When creating a new website it is always best to try and create a hierarchy of javascript files which is scalable and maintainable. A system that makes you think where you place the file during the coding process is more affective than a style guide that can be ignored.  jFrame is a system that helps the developer to organise their components.</p>

	<p>jFrame uses the following structure:</p>
	
	<pre>/v1/core/jframe.js		//jFrame and other core functionality
/v1/components/media/	//flash and AV javascript
/v1/components/ui		//javascript that affects the UI	
/v1/components/misc/	//other scripts
/v1/jquery/ui			//jQuery UI
/v1/jquery/plugins		//jQuery 3rd party plugins</pre>
	
	<p>Everything is based in a version folder. The benefit is that in the future when you need to upgrade the code you can create a V2 directory and have version 1 and version 2 running side by side rather than replacing one with another. If you manage a large website with thousands of pages it is very important that you can do this as you can slowly migrate the site over rather than attempting to update the entire website at once.</p>

	<p>However if you do not like the above structure, one of the benefits of jFrame is that you can change the folder structure to what best suits you.</p>

	<h2>Decoupling javascript from HTML using scripts as discreet components</h2>
	<p>Often when creating features that use javascript we make use of 3rd party scripts. These scripts may also make use of other javascript files.  Before you know it for one web page you may be using several files.  <a href="../examples/example1.html" title="View example 1">Example 1</a> uses the normal approach to load a survey in a thick box. It will also add a cookie to the users browser to remember the user has now seen the survey and to not show it again. 4 javascript files are needed to load up all the functionality needed.</p>

	<pre><code>&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="javascripts_old/jquery.thickbox.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="javascripts_old/jquery.cookie.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="javascripts_old/survey.js"&gt;&lt;/script&gt;</code></pre>

	<p>When we add these files to a web page we take care to add all the javascript files in the right order to get our new piece of functionality working.  If we update the javascript and this alters the dependancies we would have to update each web page using this code.</p>

	<p>jFrame abstracts the javascript implementation from the web page by using a lazy loading system. <a href="../examples/example2.html" title="View example 2">Example 2</a> takes the previous example but uses jFrame. Rather than the several javascript files in the HTML file, we now have this:</p>

	<pre><code>&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="javascripts/v1/core/jFrame.js"&gt;&lt;/script&gt;</code></pre>


	<p>To load and execute the survey functionality, we use the following command:</p>

	<pre><code>$.jFrame.start('survey', function() {	
	$.Example.survey(
			'survey.html',
			'jFrameSurvey2' //name of cookie to add
	);
});</code></pre>


	<p>Through the start method, the framework will automatically load any javascript files needed  for the survey functionality and will then execute the survey javascript.  jFrame has abstracted the files needed for a piece of functionality as each piece of functionality is now treated as a discreet component.</p>

	<p>From this you can see the power of decoupling, you could completely change the javascript implementation of the survey module and you would not have to change the code in the web page.</p>

	<p>The files are loaded into the webpage through an AJAX GET request.</p> 

	<h3>Using selectors in jFrame</h3>
	<p>One of the best features of jQuery is the ability to use selectors, we can still do this using jFrame as in <a href="../examples/example3.html" title="View examples 3">example 3</a>:</p>
	
	<pre><code>$.jFrame.start('hideshow', function(){
	$('div.hideshowWidget').Example().HideShow();
});</code></pre>


	<h3>Adding a javascript file to jFrame as a component</h3>
	<p>You must register a file within jFrame as a component before you can call it. Therefore all files have to be added in one centralised place. It is hoped that this will help developers decide the best place to logically add a file in the file system rather than add everything to the root javascript directory.</p>

	<p>Viewing <a href="../examples/javascripts/v1/core/jFrame.js" title="View the jFrame javascript">jFrame.js</a>, you will see at line 502 the commands to register a javascript file with jFrame:</p>

	<pre><code>$.jFrame.addComponent('survey',
	'javascripts/v1/components/survey.js', false);</code></pre>

	<ul>
		<li>&#8220;survey&#8221; is the component name you use to start the functionality. This should be descriptive of the procedure rather than of the code, i.e. use &#8220;surveyPopup&#8221; rather than &#8220;surveyLocalPopup&#8221; or &#8220;surveyMonkeyPopup&#8221;</li>
		<li>&#8220;javascripts/v1/components/survey.js&#8221; is the path to the javascript file</li>
		<li>&#8220;false&#8221; is to cache the file or not</li>
	</ul>

	<h3>Dependancies in javascript files</h3>
	<p>If you have coded some javascript that is dependent on other javascript files you use jFrame to call in the required files before executing any code from inside the javascript file itself rather than on the web page. To do this you first add the components to jFrame, for example with our survey example (lines 509 and 512, line wraps marked &raquo; <em>&#8212;Ed</em>):</p>

	<pre><code>$.jFrame.addComponent('cookies','javascripts/v1/&raquo;
	jqueryPlugins/jquery.cookie.js', true);
$.jFrame.addComponent('thickbox', 'javascripts/v1/&raquo;
	jqueryPlugins/jquery.thickbox.js', true);</code></pre>
	
	<p>Then in your custom javascript file (in this case <a href="../examples/javascripts/v1/components/survey.js" title="View the survey javascript">survey.js</a>) you can utilise the useComponent method.</p>  

	<pre><code>$.jFrame.useComponents('cookies,thickbox', 
	function () {
		$.Example.survey.init(surveyLink, cookieName, 
									options);
	});</code></pre>

	<p>This loads the cookie and thickbox javascript before executing the $.Example.survey.init method which starts the survey functionality.</p>

	<p>You can call in as many dependancies as you want, separate each dependency with a comma.</p>

	<p>See <a href="../examples/javascripts/v1/components/survey.js" title="View survey.js">survey.js</a> for more details.</p>

	<h2>The ability to use namespaces</h2>
	<p>Namespaces are a useful way of breaking down functionality into different compartments. jQuery has a global namespace which you use when creating or calling a plugin. By using namespacing you reduce the likelihood of a conflict.</p>

	<p>For example jFrame functions all sit in the <code>jFrame</code> namespace and all example javascript files used in this report are in the <code>Example</code> namespace.</p>

	<p>To create a new namespace, use the following commands:</p>

	<pre><code>$.Example = {};
$.namespace("Example");</code></pre>

	<p>The code to allow namespacing and still use jQuery selectors comes courtesy of <a href="http://bililite.com/blog/2008/08/05/namespaces-in-jquery" title="Website which created the namespace code">Bililite</a> and we simply added it to the jFrame. If you do not wish to use namespacing you do not need to use it. </p>

	<h2>Loading javascripts for the current page or user path</h2>
	<p>A good practice when using javascript is to merge all javascript files together.</p>

	<p>Merging files is normally better for small websites with a small javascript code base.  For large websites this is not the most optimal solution. Even if you packed all the javascript into one file, a normal user may only use a small amount of features in this file. This creates a very heavy initial page load for very little benefit to the user. </p>

	<p>jFrame is a better solution as in this case it lazy loads only the scripts necessary for the user&#8217;s journey.</p>

	<h2>Caching and preloading</h2>
	<p>You can cache files through jFrame. You do this whenever you add a component.  To have a component cached, use the following command (line wraps marked &raquo; <em>&#8212;Ed.</em>):</p>

	<pre><code>$.jFrame.addComponent('survey','javascripts/v1/&raquo;
		components/survey.js', true);</code></pre>

	<p>If you do not want it cached, use the following (line wraps marked &raquo; <em>&#8212;Ed.</em>):</p>

	<pre><code>$.jFrame.addComponent('survey','javascripts/v1/&raquo;
			components/survey.js', false);</code></pre>

	<h3>Important note on caching</h3>
	<p>If you do enable caching and then subsequently update your file, change the filename as browsers will continue to use the cached file before it was updated.  
	When debugging code, set caching to false as it will save you from having to clear the cache after every page refresh.</p>

	<h3>Preloading</h3>
	<p>If you do set you files up to be cached you can set jFrame to start preloading them on a set page. For instance the home page. To preload use the following command:</p>

	<pre><code>$.jFrame.preloader();</code></pre>

	<p>jFrame will start to load in each file that has been added as a component. As the files have been set to be cached this will mean that the browser will cache the file and on subsequent pages it will not need to be downloaded from the server again decreasing page load times.</p>

	<h2>Verbose debugging</h2>
	<p>jFrame also comes with a verbose debugger which fails gracefully in IE.  You can set the verbosity level by changing line 467 in <a href="../examples/javascripts/v1/core/jFrame.js" title="View the jFrame javascript">jFrame</a>:</p>

	<pre><code>$.jFrame.debug.currentDebugVerbosity 
			= $.jFrame.debug.debugVerbosity.low</code></pre>

	<p>The verbosity choices are:</p>
	
	<ul>
		<li><code>high</code> - will return the most debugging from inside jFrame as possible</li>
		<li><code>medium</code> - will return high level debugging messages from jFrame only</li>
		<li><code>low</code> (default) - does not return any debugging from the jFrame, would only return calls from outside jFrame</li>
	</ul>

	<p>You can also use debugging yourself in applications:</p>

	<pre><code>$.jFrame.debug('hello world');</code></pre>

	<p>This will automatically debug as a low verbosity but you can change this if needed:</p>

	<pre><code>$.jFrame.debug('hello world', null, 
			$.jFrame.debug.debugVerbosity.high);</code></pre>

	<p>The debugger works like console.log but has the advantage of failing gracefully in IE rather than crashing like console.log does. If you wish to debug IE you can add <a href="http://getfirebug.com/lite.html" title="View the FIrebug Lite webpage">Firebug Lite</a> and the debugger will output to the console.</p>

	<p>You can even set the verbosity higher during the execution of a particular script if you need to, for example:</p>

	<pre><code>$.jFrame.debug.currentDebugVerbosity 
			= $.jFrame.debug.debugVerbosity.high;</code></pre>

	<h2>Dealing with core functionality</h2>
	<p>If you need to use a number of different scripts which are core and are loaded up on every page, an ant script has been created.  The script will merge all core functionality into the jFrame file. It will also minify all javascript files using the <a href="http://developer.yahoo.com/yui/compressor/" title="More information on the YUI Compressor">YUICompressor</a>.</p>

	<p>As long as you have updated line 493 in <a href="../examples/javascripts/v1/core/jFrame.js" title="View the jFrame javascript">jFrame.js</a> and have run the ant script,  jFrame will recognize core files as part of itself and will not attempt to load them in.  This will reduce the amount of GET calls that could potentially occur.</p>
	
	<p>The Ant script is available for download on the <a href="http://code.google.com/p/jsjframe/" title="Go to the jFrame website">jFrame Google Code website</a>.</p>
	

	<h2>Auto executing components</h2>
	<p>The addComponent function has an option of an auto execute function.  This will be called every time you start the script. For example (line wraps marked &raquo; <em>&#8212;Ed</em>):</p>

	<pre><code>$.jFrame.addComponent('linkTracker','javascripts/&raquo;
		v1/core/jFrame.js', false, function() {
				$.Example.LinkTracker();
});</code></pre>

	<h2>Use it</h2>
	<p>jFrame is released as open source under the Apache license. Try new ways of using it and let us know, we are still finding new uses for jFrame ourselves. We are using it on most of the <a href="http://www.britishmuseum.org">British Museum website</a>.</p>


	<p>You may find documentation and downloaded it from <a href="http://code.google.com/p/jsjframe/" title="View the jFrame website at Google Code">Google Code</a>.</p>

	<h2>Acknowledgments</h2>
	<p>jFrame would have never been written if it was not for the following people and groups who inspired us:</p>
	
	<ul>
		<li><a href="http://24ways.org/2007/keeping-javascript-dependencies-at-bay">Christian Heilmann</a></li>
		<li><a href="http://docs.jquery.com/About">jQuery team</a></li> 
		<li><a href="http://bililite.com/blog/2008/08/05/namespaces-in-jquery">Bililite</a></li> 
		<li><a href="http://developer.yahoo.com/yui/">YUI team</a></li>
	</ul> 

</div></div>
</body>
</html>